package Noyau;

import java.awt.geom.Point2D;

public class Rail extends CheminChariot
{
	@Override
	public boolean PeutAjouterChariot(Chariot newChariot)
	{
		// We want to make sure that we have enough room left to fit the new chariot.
		if (this.chariots.size() > 0)
		{
			Chariot lastChariot = this.chariots.get(this.chariots.size() - 1);
			double position = lastChariot.getPosition() * (this.getVisualSize() - lastChariot.getSize());

			if ((position - (lastChariot.getSize() / 2)) <= (newChariot.getSize() / 2))
			{
				return false;
			}
		}

		return true;
	}

	@Override	
	public boolean AjouterChariot(Chariot newChariot) 
	{		
		if (!this.PeutAjouterChariot(newChariot))
		{
			return false;
		}

		// Otherwise, we add the chariot to the list.
		newChariot.setPosition(0);
		this.CreerChariot(newChariot);

		return true;
	}

	@Override
	public void TickHorloge() {
		// We retrieve our size.
		double size = this.getVisualSize();

		// We initialize the maximum vitesse that we currently have.
		double previousPosition = Double.MAX_VALUE;
		double vitessePrevious = Double.MAX_VALUE;

		// For each chariot (sorted by highest position, FIFO), we try to
		// make them move, if it's possible.		
		int index = 0;
		while (index < this.chariots.size())
		{
			// We retrieve the chariot at Index index.
			Chariot chariot = this.chariots.get(index);

			// We compute the new position of this chariot.
			double vitesse = chariot.getVitesse();			
			double position = chariot.getPosition() + vitesse / size;

			// We check collisions.
			double distanceToPrevious = (previousPosition - position) * size;
			if (distanceToPrevious < chariot.getSize())
			{
				vitesse = vitessePrevious;
				position = chariot.getPosition() + (vitesse / size);
			}



			if (position > 1)
			{
				// If we don't have any sortie, we stop the chariots.
				if (this.sorties.size() == 0)
				{
					break;
				}

				// If the chariot is out of the tapis, we try to give it to the sortie.				
				InterfaceChariot firstSortie = this.sorties.get(0);
				if (!firstSortie.AjouterChariot(chariot))
				{
					break;
				}

				this.chariots.remove(chariot);
			}
			else
			{
				// We make sure we have enough space for the chariot.
				if (!(((1 - position) * size) < chariot.getSize() && this.sorties.size() > 0 && !this.sorties.get(0).PeutAjouterChariot(chariot)))
				{
					// We update the position of the chariot.
					chariot.setPosition(position);
					previousPosition = position;
					vitessePrevious = vitesse;
				}
				else
				{
					previousPosition = chariot.getPosition();
					vitessePrevious = 0;
				}

				index++;
			}
		}		

		this.setChanged();
		this.notifyObservers();
	}

	@Override
	public Point2D getCenter()
	{
		if (this.entrees.size() == 0)
		{
			return this.getOrigine();
		}

		InterfaceChariot firstEntree = this.entrees.get(0);

		double x = (firstEntree.getOrigine().getX() + this.getOrigine().getX()) / 2;
		double y = (firstEntree.getOrigine().getY() + this.getOrigine().getY()) / 2;

		return new Point2D.Double(x, y);
	}
	
	@Override
	public double getSize()
	{
		// If we have no entree, we return a length of 0.
		if (this.entrees.size() == 0)
		{
			return 0;
		}

		InterfaceChariot firstEntree = this.entrees.get(0);

		// Otherwise, we calculate our length using the entree's origine point.
		double diffX = this.origine.getX() - firstEntree.getOrigine().getX();
		double diffY = this.origine.getY() - firstEntree.getOrigine().getY();

		return Math.sqrt(Math.pow(diffX, 2) + Math.pow(diffY, 2));
	}

	@Override
	public int getZBuffer()
	{
		return 0;
	}

	@Override
	public void click()
	{
		// If this Rail is clicked, we see if we have an aiguillage waiting for a choice from the user, and if
		// it's the case, we tell it we've been chosen.
		if (!this.aeroport.isModeManuel())
		{
			return;
		}

		if (this.entrees.size() == 0)
		{
			return;
		}

		InterfaceChariot firstEntree = this.entrees.get(0);
		if (!(firstEntree instanceof Aiguillage))
		{
			return;
		}

		Aiguillage entreeAiguillage = (Aiguillage)firstEntree;
		if (!entreeAiguillage.isWaitingForUser())
		{
			return;
		}

		entreeAiguillage.setSortieManuel(this);
	}
}
